package han.chensing.latos.maker.res;

import com.badlogic.gdx.graphics.g2d.freetype.FreeTypeFontGenerator;
import com.badlogic.gdx.utils.Disposable;

import java.util.HashMap;
import java.util.Map;
import java.util.Queue;
import java.util.Set;
import java.util.concurrent.LinkedBlockingQueue;

@SuppressWarnings("SameParameterValue")
public class Res {
    private static Res res;
    private final HashMap<String, Object> resources;
    private final Queue<LoadEntry> loadEntries;
    private int loadTotal = 0;
    private int loadedTotal = 0;

    public static Res get() {
        if (res == null)
            res = new Res();
        return res;
    }

    public Res() {
        resources = new HashMap<>();
        loadEntries = new LinkedBlockingQueue<>();
    }

    public void fakeLoadAll() {
        FreeTypeFontGenerator.setMaxTextureSize(10240);
        fakeLoadSkin("skinBasic","ui/skin/uiskin.json");
        fakeLoadSound("tapSound","game/sound/hitSong0.wav");
        fakeLoadSound("dragSound","game/sound/hitSong1.wav");
        fakeLoadSound("flickSound","game/sound/hitSong2.wav");
        fakeLoadTexturePair("tap","game/notes/tapNote.png");
        fakeLoadTexturePair("drag","game/notes/dragNote.png");
        fakeLoadTexturePair("flick","game/notes/flickNote.png");
        fakeLoadTexturePair("shapeDrawerRegion","ui/shape_drawer/pixel.png");
        fakeLoadFileHandle("allCharacters","ui/font/full_debug.txt");
        fakeLoadTTFGenerator("fontDengGenerator", "ui/font/dengb.ttf");
        fakeLoadTTF("fontDeng", "fontDengGenerator", 20);
    }

    public void load(String name, Object o) {
        resources.put(name, o);
    }

    public LoadEntry readLoadSingle() {
        LoadEntry poll = loadEntries.poll();
        if (poll == null) return null;
        loadedTotal++;
        load(poll.name, poll.realLoad(res));
        return poll;
    }

    public void disposeAll() {
        Set<Map.Entry<String, Object>> entries = resources.entrySet();
        for (Map.Entry<String, Object> entry : entries) {
            if (entry.getValue() instanceof Disposable disposable) {
                disposable.dispose();
            }
        }
    }

    @SuppressWarnings({"unchecked", "unused"})
    public <T> T get(String name, Class<T> tClass) {
        return (T) resources.get(name);
    }

    public int getLoadTotal() {
        return loadTotal;
    }

    public int getLoadedTotal() {
        return loadedTotal;
    }

    private void fakeLoadTexturePair(String name, String path) {
        fakeLoadTexture(name + "T", path);
        fakeLoadTextureRegion(name, name + "T");
    }

    private void fakeLoadTexture(String name, String path) {
        loadTotal++;
        loadEntries.offer(new LoadEntry.TextureEntry(name, path));
    }

    private void fakeLoadTextureRegion(String name, String textureName) {
        loadTotal++;
        loadEntries.offer(new LoadEntry.TextureRegionEntry(name, textureName));
    }

    private void fakeLoadSound(String name, String path) {
        loadTotal++;
        loadEntries.offer(new LoadEntry.SoundRegionEntry(name, path));
    }

    private void fakeLoadTTFGenerator(String name, String path) {
        loadTotal++;
        loadEntries.offer(new LoadEntry.TTFGeneratorEntry(name, path));
    }

    private void fakeLoadTTF(String name, String generatorName, int size) {
        loadTotal++;
        loadEntries.offer(new LoadEntry.TTFEntry(name, generatorName, size));
    }

    private void fakeLoadSkin(String name,String path){
        loadTotal++;
        loadEntries.offer(new LoadEntry.SkinEntry(name,path));
    }

    private void fakeLoadShadeProgram(String name,String vertPath,String fragPath){
        loadTotal++;
        loadEntries.offer(new LoadEntry.ShadeProgramEntry(name, vertPath, fragPath));
    }

    private void fakeLoadFileHandle(String name,String path){
        loadTotal++;
        loadEntries.offer(new LoadEntry.FileHandleEntry(name, path));
    }
}